昨天初步介紹了類別的基本組成與一些建構子的概念,但其實建構子之間還有一個觀念昨天沒有提到 “初始化塊” ( Initializer Block )
初始化塊有別於次建構子,它的位階較接近主建構子,常被視為主建構子的延伸區塊,但它不具備傳入屬性的能力。
class Person(firstName: String, lastName: String) {
val fullName: String
init {
fullName = "$firstName-$lastName"
println("Initializer block executed: $fullName")
}
}
fun main(){
Person("John", "Wei") // Initializer block executed: John-Wei
}
上述程式碼定義了一個名為 Person 的類別,它具有兩個參數的主建構子,分別是 firstName
(名字)和 lastName
(姓氏)。在這個類別中,有一個屬性 fullName
用於儲存完整名字,它是在初始化塊(init block)中被賦值的。
在初始化塊中,fullName
的值被設定為 $firstName-$lastName
,並且會輸出一條包含組合後的 fullName
的字串。
當然,初始化塊也可以跟次建構子一起使用,我們看下方範例:
class Person(firstName: String, lastName: String) {
val fullName: String
init {
fullName = "$firstName-$lastName"
println("Initializer block executed: $fullName")
}
constructor(firstName: String) : this(firstName, "Jack") {
println("Secondary constructor called")
}
}
fun main() {
Person("Wang")
// Initializer block executed: Wang-Jack
// Secondary constructor called
}
跟第一個範例不同,這次 Person
類別還有一個次建構子,只接受一個參數 firstName
。這個次要建構子使用 this(firstName, "Jack")
的語法,呼叫了主建構子,並且將 lastName
參數設定為 "Jack"。在這個次要建構子中,還有一行程式碼顯示訊息,指示次要建構子已被呼叫。
最後,在 main 函式中,創建了一個 Person
的物件,只傳入了名字 "Wang"。這樣,主建構子和次要建構子的程式碼就會被執行。由於使用的是次要建構子,所以它會呼叫主建構子,並且將 lastName
設定為 "Jack"。
如果今天程式碼中存在多個初始化塊,它並不會因為放置的位置在次建構子前後影響它的執行順序,各位讀者可以先猜測一下下方程式碼的執行結果在跟下方答案對一下。
class Person(firstName: String, lastName: String) {
val fullName: String
init {
println("Initializer block 1 executed")
}
constructor(firstName: String) : this(firstName, "Doe") {
println("Secondary constructor executed")
}
init {
fullName = "$firstName $lastName"
println("Initializer block 2 executed: $fullName")
}
}
fun main() {
Person("John")
}
結果:
Initializer block 1 executed
Initializer block 2 executed: John Doe
Secondary constructor executed